package com.linxiao.hrcrm.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.exceptions.UtilException;
import com.linxiao.hrcrm.domain.CrmBalanceFlow;
import com.linxiao.hrcrm.domain.CrmCustomer;
import com.linxiao.hrcrm.domain.CrmCustomerBalance;
import com.linxiao.hrcrm.service.ICrmBalanceFlowService;
import com.linxiao.hrcrm.service.ICrmCustomerBalanceService;
import com.linxiao.hrcrm.service.ICrmCustomerService;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.domain.SysMchConfig;
import com.ruoyi.system.service.ISysMchConfigService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.linxiao.hrcrm.mapper.CrmCustomerSalaryMapper;
import com.linxiao.hrcrm.domain.CrmCustomerSalary;
import com.linxiao.hrcrm.service.ICrmCustomerSalaryService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * 客户薪资记录Service业务层处理
 *
 * @author zhoudong
 * @date 2024-01-03
 */
@Service
public class CrmCustomerSalaryServiceImpl implements ICrmCustomerSalaryService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @Resource
    private CrmCustomerSalaryMapper crmCustomerSalaryMapper;
    @Resource
    private ICrmCustomerService crmCustomerService;
    @Resource
    private ICrmCustomerBalanceService crmCustomerBalanceService;
    @Resource
    private ICrmBalanceFlowService crmBalanceFlowService;
    @Resource
    private ISysMchConfigService mchConfigService;

    /**
     * 查询客户薪资记录
     *
     * @param id 客户薪资记录主键
     * @return 客户薪资记录
     */
    @Override
    public CrmCustomerSalary selectCrmCustomerSalaryById(Long id) {
        return crmCustomerSalaryMapper.selectCrmCustomerSalaryById(id);
    }

    /**
     * 查询客户薪资记录列表
     *
     * @param crmCustomerSalary 客户薪资记录
     * @return 客户薪资记录
     */
    @Override
    public List<CrmCustomerSalary> selectCrmCustomerSalaryList(CrmCustomerSalary crmCustomerSalary) {
        List<CrmCustomerSalary> salaries = crmCustomerSalaryMapper.selectCrmCustomerSalaryList(crmCustomerSalary);
        if (CollUtil.isNotEmpty(salaries)) {
            salaries.parallelStream().forEach(ccs -> {
                CrmCustomer crmCustomer = crmCustomerService.selectCrmCustomerById(ccs.getCustomerId());
                if (crmCustomer != null) {
                    ccs.setCustomerName(crmCustomer.getCustomerName());
                } else {
                    ccs.setCustomerName("未知");
                }
            });
        }
        return salaries;
    }

    /**
     * 新增客户薪资记录
     *
     * @param crmCustomerSalary 客户薪资记录
     * @return 结果
     */
    @Override
    public int insertCrmCustomerSalary(CrmCustomerSalary crmCustomerSalary) {
        // 获取当天所有的签卡记录

        // 获取第一条签卡、最后一条签卡（签卡开始、结束时间）

        // 计算薪资

        crmCustomerSalary.setCreateTime(DateUtils.getNowDate());
        return crmCustomerSalaryMapper.insertCrmCustomerSalary(crmCustomerSalary);
    }

    /**
     * 修改客户薪资记录
     *
     * @param crmCustomerSalary 客户薪资记录
     * @return 结果
     */
    @Override
    public int updateCrmCustomerSalary(CrmCustomerSalary crmCustomerSalary) {
        crmCustomerSalary.setUpdateTime(DateUtils.getNowDate());
        return crmCustomerSalaryMapper.updateCrmCustomerSalary(crmCustomerSalary);
    }

    /**
     * 批量删除客户薪资记录
     *
     * @param ids 需要删除的客户薪资记录主键
     * @return 结果
     */
    @Override
    public int deleteCrmCustomerSalaryByIds(Long[] ids) {
        return crmCustomerSalaryMapper.deleteCrmCustomerSalaryByIds(ids);
    }

    /**
     * 删除客户薪资记录信息
     *
     * @param id 客户薪资记录主键
     * @return 结果
     */
    @Override
    public int deleteCrmCustomerSalaryById(Long id) {
        return crmCustomerSalaryMapper.deleteCrmCustomerSalaryById(id);
    }

    /**
     * 批量审核通过
     * @param ids
     * @return
     */
    @Override
    public int audits(Long[] ids) {
        return crmCustomerSalaryMapper.audits(ids);
    }

    /**
     * 批量结算
     * @param ids
     * @return
     */
    @Transactional
    @Override
    public int settle(Long[] ids) {
        AtomicInteger i = new AtomicInteger();
        // 查询选中的记录
        List<CrmCustomerSalary> salaries = crmCustomerSalaryMapper.selectByIds(ids);
        salaries.parallelStream().forEach(s -> {
            // 仅审核通过的、并且是时薪的参与结算
            if (CrmCustomerSalary.AUDIT_STATUS_PASS.equals(s.getAuditStatus())
                    && CrmCustomerSalary.SALARY_UNIT_HOUR.equals(s.getSalaryUnit())) {

                if (s.getSalaryRate() == null) {
                    logger.error("当前记录，未设置单位薪资，不参与结算, id:{}", s.getId());
                    return;
                }

                // 时薪换算成分钟
                BigDecimal minuteAmount = s.getSalaryRate().divide(new BigDecimal(60), 10, RoundingMode.HALF_DOWN);
                BigDecimal sumAmount;
                long hours = s.getWorkMinute() / 60;
                long minute = s.getWorkMinute() % 60;
                // 判断时薪计算方式
                switch (s.getHourlyRateCalculation()) {
                    case CrmCustomerSalary.SALARY_HOURLY_RATE_CALCULATION_ACCURATE:
                        // 精确计算，精确到分钟
                        sumAmount = s.getSalaryRate().multiply(BigDecimal.valueOf(hours));
                        sumAmount = sumAmount.add(minuteAmount.multiply(BigDecimal.valueOf(minute)));
                        s.setSalaryAmount(sumAmount);
                        break;
                    case CrmCustomerSalary.SALARY_HOURLY_RATE_CALCULATION_QUARTER:
                        if (minute <= 15) {
                            // 不满15分钟，按照整点算
                            sumAmount = s.getSalaryRate().multiply(BigDecimal.valueOf(hours));
                            s.setRemark("不满15分钟部分，按整点计算");
                        } else if (minute > 15 && minute <= 30) {
                            // 超过15，小于30，按照半点算
                            sumAmount = s.getSalaryRate().multiply(BigDecimal.valueOf(hours));
                            sumAmount = sumAmount.add(minuteAmount.multiply(BigDecimal.valueOf(30)));
                            s.setRemark("16至30分钟部分，按照半小时计算");
                        } else if (minute > 30 && minute <= 45) {
                            // 超过30，小于45，按照半点算
                            sumAmount = s.getSalaryRate().multiply(BigDecimal.valueOf(hours));
                            sumAmount = sumAmount.add(minuteAmount.multiply(BigDecimal.valueOf(30)));
                            s.setRemark("31至45分钟部分，按照半小时计算");
                        } else {
                            // 超过45，按照一小时算
                            sumAmount = s.getSalaryRate().multiply(BigDecimal.valueOf(hours + 1L));
                            s.setRemark("45至59部分，按照一小时计算");
                        }
                        s.setSalaryAmount(sumAmount);
                        // 刻钟计算
                        break;
                    case CrmCustomerSalary.SALARY_HOURLY_RATE_CALCULATION_HALF:
                        // 半点计算
                        sumAmount = s.getSalaryRate().multiply(BigDecimal.valueOf(hours));
                        if (minute < 30) {
                            // 不满30分钟，忽略
                            s.setRemark("不满30分钟部分，忽略不计");
                        } else {
                            // 超过30，不满一小时，按照30分钟计算
                            sumAmount = sumAmount.add(minuteAmount.multiply(BigDecimal.valueOf(30)));
                            s.setRemark("超过30，不满一小时部分，按照30分钟计算");
                        }
                        s.setSalaryAmount(sumAmount);
                        break;
                    case CrmCustomerSalary.SALARY_HOURLY_RATE_CALCULATION_HOUR:
                        // 小时计算
                        sumAmount = s.getSalaryRate().multiply(BigDecimal.valueOf(hours));
                        s.setRemark("不满一小时部分，忽略不计");
                        s.setSalaryAmount(sumAmount);
                        break;
                }
                s.setSalaryAmount(s.getSalaryAmount().setScale(2, RoundingMode.HALF_DOWN));
                s.setPaymentStatus(CrmCustomerSalary.PAYMENT_STATUS_WAITING);
                i.addAndGet(updateCrmCustomerSalary(s));
            }
        });
        return i.get();
    }

    /**
     * 批量发薪
     * @param ids 客户的ID数组
     * @return 发放成功的数量
     */
    @Transactional
    @Override
    public int grant(Long[] ids) {
        // 计数器，用于记录发放成功的数量
        AtomicInteger i = new AtomicInteger();
        // 查询选中的记录
        List<CrmCustomerSalary> salaries = crmCustomerSalaryMapper.selectByIds(ids);

        // 获取商户配置
        SysMchConfig mchConfig = null;
        if (CollUtil.isNotEmpty(salaries)) {
            mchConfig = mchConfigService.selectByMchId(salaries.get(0).getMchId());
        }

        SysMchConfig finalMchConfig = mchConfig;
        salaries.parallelStream().forEach(s -> {
            // 仅发放待发放的数据
            if (CrmCustomerSalary.PAYMENT_STATUS_WAITING.equals(s.getPaymentStatus())) {
                // 直接发放，还是发放到余额
                CrmCustomerBalance crmCustomerBalance = null;
                BigDecimal previousBalance = null;
                if (finalMchConfig == null || SysMchConfig.balance.equals(finalMchConfig.getBalanceGrantConfig())) {
                    // 余额表+
                    // 查询客户的余额记录，如果没有则插入一条新的记录
                    crmCustomerBalance = crmCustomerBalanceService.selectByCustomerIdAndInsert(s.getMchId(), s.getCustomerId());
                    // 保存之前的余额
                    previousBalance = crmCustomerBalance.getBalanceAmount();
                    // 更新余额
                    crmCustomerBalance.setBalanceAmount(crmCustomerBalance.getBalanceAmount().add(s.getSalaryAmount()));
                    // 更新余额记录
                    crmCustomerBalanceService.updateCrmCustomerBalance(crmCustomerBalance);
                } else {
                    // TODO 直接转账到银行卡，暂未完成
                }
                

                // 流水表+
                // 创建一条新的流水记录
                CrmBalanceFlow crmBalanceFlow = new CrmBalanceFlow();
                crmBalanceFlow.setCustomerId(s.getCustomerId());
                crmBalanceFlow.setMchId(s.getMchId());
                crmBalanceFlow.setBusinessType(CrmBalanceFlow.BUSINESS_TYPE_GRANT);
                crmBalanceFlow.setAccountType(CrmBalanceFlow.ACCOUNT_TYPE_BALANCE);
                crmBalanceFlow.setBusinessOrderId(s.getId() + "");
                crmBalanceFlow.setPreviousBalance(previousBalance == null ? BigDecimal.ZERO : previousBalance);
                crmBalanceFlow.setCurrentBalance(crmCustomerBalance == null ? BigDecimal.ZERO : crmCustomerBalance.getBalanceAmount());
                // 插入流水记录
                crmBalanceFlowService.insertCrmBalanceFlow(crmBalanceFlow);

                // 发放状态改
                // 更新发放状态为已发放
                s.setPaymentStatus(CrmCustomerSalary.PAYMENT_STATUS_GRANT);
                // 更新发放记录，并将更新的数量加到计数器上
                i.addAndGet(updateCrmCustomerSalary(s));
            }
        });
        // 返回发放成功的数量
        return i.get();
    }

    /**
     * 获取某员工的薪资记录
     * @param crmCustomerSalary
     * @return
     */
    @Override
    public List<CrmCustomerSalary> findByUser(CrmCustomerSalary crmCustomerSalary) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        CrmCustomer customer = crmCustomerService.selectCrmCustomerByMemberId(crmCustomerSalary.getMchId(), loginUser.getUserId());
        if (customer == null) {
            throw new UtilException("客户信息有误");
        }
        crmCustomerSalary.setCustomerId(customer.getId());
        List<CrmCustomerSalary> salaries = crmCustomerSalaryMapper.selectCrmCustomerSalaryList(crmCustomerSalary);
        if (CollUtil.isNotEmpty(salaries)) {
            salaries.parallelStream().forEach(c -> c.setCustomerName(customer.getCustomerName()));
        }
        return salaries;
    }
}
